namespace PeaceBlogData
{
    using System;
    using System.Data.Entity;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Linq;
    using PeaceBlogData.Tables;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using PagedList;

    public partial class PeaceBlogEntity : DbContext
    {
        public PeaceBlogEntity()
            : base("name=PeaceBlogEntity")
        {

        }
        public virtual DbSet<Menus> Menus { get; set; }
        public virtual DbSet<Authors> Authors { get; set; }
        public virtual DbSet<Categories> Categories { get; set; }
        public virtual DbSet<Files> Files { get; set; }
        public virtual DbSet<Logs> Logs { get; set; }
        public virtual DbSet<Pages> Pages { get; set; }
        public virtual DbSet<Posts> Posts { get; set; }
        public virtual DbSet<Settings> Settings { get; set; }
        public virtual DbSet<Sliders> Sliders { get; set; }
        public virtual DbSet<Stats> Stats { get; set; }
        public virtual DbSet<Tags> Tags { get; set; }
        public virtual DbSet<Widgets> Widgets { get; set; }
        public virtual DbSet<PostStats> PostStats { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Authors>()
                .Property(e => e.About)
                .IsUnicode(false);

            modelBuilder.Entity<Authors>()
                .Property(e => e.SocialInfo)
                .IsUnicode(false);
            
            modelBuilder.Entity<Files>()
                .HasMany(e => e.Authors)
                .WithOptional(e => e.Files)
                .HasForeignKey(e => e.ImageID);

            modelBuilder.Entity<Files>()
                .HasMany(e => e.Pages)
                .WithOptional(e => e.Files)
                .HasForeignKey(e => e.Partial);

            modelBuilder.Entity<Files>()
                .HasMany(e => e.Widgets)
                .WithRequired(e => e.Files)
                .WillCascadeOnDelete(false);
            
            modelBuilder.Entity<Menus>()
                .Property(e => e.Links)
                .IsUnicode(false);

            modelBuilder.Entity<Pages>()
                .Property(e => e.Content)
                .IsUnicode(false);

            modelBuilder.Entity<Posts>()
                .Property(e => e.PostExtension)
                .IsUnicode(false);

            modelBuilder.Entity<Posts>()
                .Property(e => e.Content)
                .IsUnicode(false);

            modelBuilder.Entity<Posts>()
                .Property(e => e.SpecialMeta)
                .IsUnicode(false);

            modelBuilder.Entity<Posts>()
                .HasMany(e => e.PostStats)
                .WithRequired(e => e.Posts)
                .WillCascadeOnDelete(false);

            modelBuilder.Entity<Categories>()
                .HasMany(e => e.Posts)
                .WithMany(e => e.Categories)
                .Map(m => m.ToTable("PostToCategory").MapLeftKey("CategoryID").MapRightKey("PostID"));

            modelBuilder.Entity<Posts>()
                .HasMany(e => e.Tags)
                .WithMany(e => e.Posts)
                .Map(m => m.ToTable("TaggedToPost").MapLeftKey("PostID").MapRightKey("TagID"));

            modelBuilder.Entity<Settings>()
                .Property(e => e.Value)
                .IsUnicode(false);

            modelBuilder.Entity<Sliders>()
                .Property(e => e.Content)
                .IsUnicode(false);

            modelBuilder.Entity<Widgets>()
                .Property(e => e.Parametres)
                .IsUnicode(false);
            

        }

        #region Settings

        public async Task<List<Settings>> GetAllSettings()
        {
            return await (from setting in Settings
                          select setting).ToListAsync();
        }

        public List<Settings> GetAllSettingsWithoutAsync()
        {
            return (from setting in Settings
                    select setting).ToList();
        }

        public async Task<Settings> GetSetting(string key)
        {
            return await (from setting in Settings
                          where setting.Key == key
                          select setting).FirstOrDefaultAsync();
        }

        public async Task<bool> UpdateSetting(Settings setting)
        {
            var oldSetting = await GetSetting(setting.Key);
            if (oldSetting == null)
                return false;
            oldSetting.Value = setting.Value;
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region Categories

        public List<Categories> GetAllCategories()
        {
            return (from ct in Categories
                    select ct).ToList();
        }


        public async Task<List<Categories>> GetAllCategoriesAsync()
        {
            return await (from ct in Categories
                          select ct).ToListAsync();
        }

        public async Task<List<Categories>> GetSubCategories(int SubCategoryID)
        {
            return await (from ct in Categories
                          where ct.SubCategoryID == SubCategoryID
                          select ct).ToListAsync();
        }

        public async Task<Categories> GetCategory(int CategoryID)
        {
            return await (from ct in Categories
                          where ct.CategoryID == CategoryID
                          select ct).FirstOrDefaultAsync();
        }

        public async Task<Categories> GetCategory(string Url)
        {
            return await (from ct in Categories
                          where ct.ShortName == Url
                          select ct).FirstOrDefaultAsync();
        }

        public async Task<List<Categories>> GetSortedCategories()
        {
            return (await GetAllCategoriesAsync()).OrderBy(p => p.SortNo).ToList();
        }

        public async Task<List<Categories>> GetSortedSubCategories(int SubCategoryID)
        {
            return (await GetSubCategories(SubCategoryID)).OrderBy(p => p.SortNo).ToList();
        }

        public async Task<bool> AddCategory(Categories category)
        {
            Categories.Add(category);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> AddCategories(List<Categories> Categories)
        {
            this.Categories.AddRange(Categories);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> UpdateCategory(Categories category)
        {
            var oldCategory = await GetCategory(category.CategoryID);
            if (oldCategory == null)
                return false;
            oldCategory.Description = category.Description;
            oldCategory.FileID = category.FileID;
            oldCategory.MetaDescription = category.MetaDescription;
            oldCategory.MetaKeywords = category.MetaKeywords;
            oldCategory.MetaTitle = category.MetaTitle;
            oldCategory.Name = category.Name;
            oldCategory.ShortName = category.ShortName;
            oldCategory.SortNo = category.SortNo;
            oldCategory.SpecialMeta = category.SpecialMeta;
            oldCategory.SubCategoryID = category.SubCategoryID;
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeleteCategory(int CategoryID)
        {
            var oldCategory = await GetCategory(CategoryID);
            if (oldCategory == null)
                return false;
            Categories.Remove(oldCategory);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeleteCategories(List<int> CategoriesID)
        {

            var oldCategories = new List<Categories>();
            foreach (var CategoryID in CategoriesID)
                oldCategories.Add(await GetCategory(CategoryID));
            if (oldCategories.Count == 0)
                return false;
            Categories.RemoveRange(oldCategories);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }

        }

        #endregion

        #region Posts

        public async Task<List<Posts>> GetAllPosts()
        {
            return await (from post in Posts
                          select post).ToListAsync();
        }

        public IPagedList<Posts> Search(string search, int PageNumber = 1, int PageSize = 10)
        {
            return (from post in Posts
                    where post.Content.Contains(search) |
                    post.MetaDescription.Contains(search) |
                    post.MetaTitle.Contains(search) |
                    post.ShortDescription.Contains(search)
                    select post)
                          .OrderByDescending(p => p.SaveDate)
                          .ToPagedList(PageNumber, PageSize);
        }

        public List<Posts> GetRecentPosts(int PostCount)
        {
            return (from post in Posts
                    orderby post.SaveDate descending
                    select post).Take(PostCount).ToList();
        }

        public async Task<List<Posts>> GetRecentPostsAsync(int PostCount)
        {
            return await (from post in Posts
                          orderby post.SaveDate descending
                          select post).Take(PostCount).ToListAsync();
        }

        public IPagedList<Posts> GetAllPosts(int PageNumber = 1, int PageSize = 10)
        {
            return (from post in Posts
                    orderby post.SaveDate descending
                    select post)
                          .OrderByDescending(p => p.SaveDate)
                          .ToPagedList(PageNumber, PageSize);
        }

        public async Task<Posts> GetPostFromURL(string url)
        {
            return await (from post in Posts
                          where post.SpecialURL == url
                          select post).FirstOrDefaultAsync();
        }

        public async Task<Posts> GetPost(Guid PostID)
        {
            return await (from post in Posts
                          where post.PostID == PostID
                          select post).FirstOrDefaultAsync();
        }

        public List<Posts> GetPostsFromAuthor(int AuthorID)
        {
            return (from post in Posts
                    where post.AuthorID == AuthorID
                    select post).ToList();
        }

        public async Task<List<Posts>> GetPostsFromAuthorAsync(int AuthorID)
        {
            return await (from post in Posts
                          where post.AuthorID == AuthorID
                          select post).ToListAsync();
        }

        public async Task<List<Posts>> GetPostsFromCategory(int CategoryID)
        {
            return (await (from category in Categories
                           where category.CategoryID == CategoryID
                           select category.Posts).FirstOrDefaultAsync()).ToList();
        }

        public async Task<List<Posts>> GetPostsFromYear(int Year)
        {
            return await (from post in Posts
                          where post.SaveDate.Year == Year
                          select post).ToListAsync();
        }

        public async Task<List<Posts>> GetPostsFromMonth(int Month)
        {
            return await (from post in Posts
                          where post.SaveDate.Month == Month
                          select post).ToListAsync();
        }

        public async Task<List<Posts>> GetPostsFromDay(int Day)
        {
            return await (from post in Posts
                          where post.SaveDate.Day == Day
                          select post).ToListAsync();
        }

        public async Task<List<Posts>> GetPostsFromType(int PostType)
        {
            return await (from post in Posts
                          where post.PostType == PostType
                          select post).ToListAsync();
        }

        public async Task<List<Posts>> GetPostsFromTags(string tag)
        {
            return (await (from tg in Tags
                           where tg.Tag == tag
                           select tg.Posts).FirstOrDefaultAsync()).ToList();
        }

        public async Task<bool> AddPost(Posts post)
        {
            Posts.Add(post);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> UpdatePost(Posts post)
        {
            var oldPost = await GetPost(post.PostID);
            if (oldPost == null)
                return false;
            oldPost = post;
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeletePost(Guid PostID)
        {
            var oldPost = await GetPost(PostID);
            if (oldPost == null)
                return false;
            Posts.Remove(oldPost);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region Authors

        public async Task<List<Authors>> GetAllAuthorsAsync()
        {
            return await (from author in Authors
                          select author).ToListAsync();
        }

        public Authors GetAuthorFromLogin(string email, string password)
        {
            return (from author in Authors
                    where author.Email == email & author.Password == password
                    select author).FirstOrDefault();
        }

        public List<Authors> GetAllAuthors()
        {
            return (from author in Authors
                    select author).ToList();
        }

        public async Task<Authors> GetAuthor(int AuthorID)
        {
            return await (from ct in Authors
                          where ct.AuthorID == AuthorID
                          select ct).FirstOrDefaultAsync();
        }

        public async Task<Authors> GetAuthor(string AuthorUrl)
        {
            return await (from auth in Authors
                          where auth.AuthorUrl == AuthorUrl
                          select auth).FirstOrDefaultAsync();
        }

        public async Task<bool> AddAuthor(Authors author)
        {
            Authors.Add(author);
            try
            {
                author.SaveDate = DateTime.Now;
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> UpdateAuthor(Authors author)
        {
            var oldAuthor = await GetAuthor(author.AuthorID);
            if (oldAuthor == null)
                return false;
            oldAuthor = author;
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeleteAuthor(int AuthorID)
        {
            var oldAuthor = await GetAuthor(AuthorID);
            if (oldAuthor == null)
                return false;
            Authors.Remove(oldAuthor);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeleteAuthors(List<int> AuthorsID)
        {
            var oldAuthors = new List<Authors>();
            foreach (var AuthorID in AuthorsID)
                oldAuthors.Add(await GetAuthor(AuthorID));
            if (oldAuthors.Count == 0)
                return false;
            Authors.RemoveRange(oldAuthors);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region Pages

        public async Task<List<Pages>> GetAllPages()
        {
            return await (from page in Pages
                          select page).ToListAsync();
        }

        public async Task<Pages> GetPage(Guid PageID)
        {
            return await (from ct in Pages
                          where ct.PageID == PageID
                          select ct).FirstOrDefaultAsync();
        }

        public async Task<bool> AddPage(Pages page)
        {
            Pages.Add(page);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> UpdatePage(Pages page)
        {
            var oldPage = await GetPage(page.PageID);
            if (oldPage == null)
                return false;
            oldPage = page;
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeletePage(Guid PageID)
        {
            var oldPage = await GetPage(PageID);
            if (oldPage == null)
                return false;
            Pages.Remove(oldPage);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeleteAuthors(List<Guid> PagesID)
        {
            var oldPages = new List<Pages>();
            foreach (var PageID in PagesID)
                oldPages.Add(await GetPage(PageID));
            if (oldPages.Count == 0)
                return false;
            Pages.RemoveRange(oldPages);
            try
            {
                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }


        #endregion

        #region Files

        public async Task<List<Files>> GetAllFiles()
        {
            return await (from file in Files
                          select file).ToListAsync();
        }

        public async Task<Files> GetFileAsync(int FileId)
        {
            return await (from file in Files
                          where file.FileID == FileId
                          select file).FirstOrDefaultAsync();
        }

        public Files GetFile(int FileId)
        {
            return (from file in Files
                    where file.FileID == FileId
                    select file).FirstOrDefault();
        }

        public async Task<List<Files>> GetFilesFromType(string filetype)
        {
            return await (from file in Files
                          where file.FileType == filetype || file.FileType.Contains(filetype)
                          select file).ToListAsync();
        }

        #endregion

        #region Tags

        public List<Tags> GetAllTags()
        {
            return (from tag in Tags
                    select tag).ToList();
        }

        public async Task<List<Tags>> GetAllTagsAsync()
        {
            return await (from tag in Tags
                          select tag).ToListAsync();
        }

        public async Task<Tags> GetTag(string tag)
        {
            return await (from tg in Tags
                          where tg.Tag == tag
                          select tg).FirstOrDefaultAsync();
        }

        public List<Posts> GetPostsFromTag(string tag)
        {
            return (from tg in Tags
                    where tg.Tag == tag
                    select tg.Posts).FirstOrDefault().ToList();
        }

        #endregion
    }

}
